// jackspa, a dirt-simple LADSPA host for JACK
// Copyright (C) 2007 Nick Thomas
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of version 2 of the GNU General Public
// License as published by the Free Software Foundation; the terms of
// any later version are NOT APPLICABLE.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

#include <gtkmm/box.h>
#include <gtkmm/label.h>
#include <gtkmm/main.h>
#include <gtkmm/scale.h>
#include <gtkmm/window.h>
#include "jackspa.hpp"
using namespace Gtk;

class ControlSlider : public HScale
{
public:
    ControlSlider(state_t *state, int port);
private:
    void on_value_changed();
    float *dest;
};

int main(int argc, char **argv)
{
    Main kit(argc, argv);

    state_t state;
    jackspa_init(&state, argc, argv);

    VBox slider_box;

    for (int i = 0; i < (int)state.descriptor->PortCount; i++) {
        if (LADSPA_IS_PORT_INPUT(state.descriptor->PortDescriptors[i]) &&
            LADSPA_IS_PORT_CONTROL(state.descriptor->PortDescriptors[i])) {
            HBox *box = new HBox;
            box->set_spacing(10);
            box->pack_start(*new Label(state.descriptor->PortNames[i],
                                       ALIGN_RIGHT), PACK_SHRINK);
            box->pack_start(*new ControlSlider(&state, i),
                            PACK_EXPAND_WIDGET);
            slider_box.pack_start(*box, PACK_SHRINK);
        }
    }

    Window main_window;
    main_window.add(slider_box);
    main_window.resize(400, main_window.get_height());
    main_window.set_title(state.client_name);
    main_window.show_all_children();

    Main::run(main_window);

    return 0;
}

ControlSlider::ControlSlider(state_t *state, int port)
{
    LADSPA_PortRangeHint hint = state->descriptor->PortRangeHints[port];
    LADSPA_PortRangeHintDescriptor descriptor = hint.HintDescriptor;
    float lower_bound = hint.LowerBound;
    float upper_bound = hint.UpperBound;
    float default_value;

    dest = &state->control_port_values[port];

    if (LADSPA_IS_HINT_SAMPLE_RATE(descriptor)) {
        int sample_rate = jack_get_sample_rate(state->jack_client);
        lower_bound *= sample_rate;
        upper_bound *= sample_rate;
    }

    if (LADSPA_IS_HINT_BOUNDED_BELOW(descriptor) &&
        LADSPA_IS_HINT_BOUNDED_ABOVE(descriptor)) {
        set_range(lower_bound, upper_bound);
    } else if (LADSPA_IS_HINT_BOUNDED_BELOW(descriptor)) {
        set_range(lower_bound, 1.0);
    } else if (LADSPA_IS_HINT_BOUNDED_ABOVE(descriptor)) {
        set_range(0.0, upper_bound);
    } else {
        set_range(-1.0, 1.0);
    }

    if (LADSPA_IS_HINT_TOGGLED(descriptor)) {
        set_range(0.0, 1.0);
        set_increments(1.0, 1.0);
    }

    if (LADSPA_IS_HINT_INTEGER(descriptor)) {
        set_increments(1.0, 1.0);
        set_digits(0);
    } else {
        set_increments(0.05, 0.1);
        set_digits(2);
    }

    if (LADSPA_IS_HINT_HAS_DEFAULT(descriptor)) {
        switch (descriptor & LADSPA_HINT_DEFAULT_MASK) {
         case LADSPA_HINT_DEFAULT_MINIMUM:
            default_value = lower_bound;
            break;
         case LADSPA_HINT_DEFAULT_LOW:
            default_value = lower_bound * 0.75 + upper_bound * 0.25;
            break;
         case LADSPA_HINT_DEFAULT_MIDDLE:
            default_value = lower_bound * 0.5 + upper_bound * 0.5;
            break;
         case LADSPA_HINT_DEFAULT_HIGH:
            default_value = lower_bound * 0.5 + upper_bound * 0.5;
            break;
         case LADSPA_HINT_DEFAULT_MAXIMUM:
            default_value = upper_bound;
            break;
         case LADSPA_HINT_DEFAULT_0:
            default_value = 0.0;
            break;
         case LADSPA_HINT_DEFAULT_1:
            default_value = 1.0;
            break;
         case LADSPA_HINT_DEFAULT_100:
            default_value = 100.0;
            break;
         case LADSPA_HINT_DEFAULT_440:
            default_value = 440.0;
            break;
        }

        *dest = default_value;
    }
}

void ControlSlider::on_value_changed()
{
    *dest = get_value();
}
